package com.logic.landseaserver.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.logic.landseaserver.persistence.read.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.logic.common.domain.Code;
import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.common.util.SysUtil;
import com.logic.common.ws.dto.system.CodeDTO;
import com.logic.landseaserver.common.LandeaConstants;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.VariableChar;
import com.logic.landseaserver.common.enums.SystemCodeEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.common.util.StringTools;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.domain.Customer;
import com.logic.landseaserver.domain.CustomerVersion;
import com.logic.landseaserver.domain.Deposit;
import com.logic.landseaserver.persistence.write.CustomerVersionWriteMapper;
import com.logic.landseaserver.persistence.write.CustomerWriteMapper;
import com.logic.landseaserver.persistence.write.VerificationCodeWriteMapper;
import com.logic.landseaserver.service.ICustomer;
import com.logic.landseaserver.ws.dto.ChapterUserDTO;
import com.logic.landseaserver.ws.dto.CustomerDTO;
import com.logic.landseaserver.ws.dto.UserDTO;
import com.logic.system.domain.User;
import com.logic.system.persistence.write.OAuthAccessTokenWriteMapper;
import com.logic.system.persistence.write.UserWriteMapper;
import com.logic.system.service.ICodeService;
import com.logic.system.service.IUserService;
import com.logic.system.ws.dto.CodeConverter;


@Service
public class CustomerImpl implements ICustomer {

    private static final Logger LOG = LoggerFactory.getLogger(CustomerImpl.class);

    @Autowired
    private CustomerReadMapper customerReadMapper;
    @Autowired
    private CustomerVersionReadMapper customerVersionReadMapper;
    @Autowired
    private CustomerVersionWriteMapper customerVersionWriteMapper;
    @Autowired
    private CustomerWriteMapper customerWriteMapper;

    @Autowired
    private ClientUserReadMapper clientUserReadMapper;

    @Autowired
    private ClientUserServiceImpl clientUserServiceImpl;

    @Autowired
    private VerificationCodeWriteMapper verificationCodeWriteMapper;

    @Autowired
    private IUserService userService;
    @Autowired
    private UserWriteMapper userWriteMapper;

    @Autowired
    private ICodeService codeService;

    @Autowired
    private ContractReadMapper contractReadMapper;

    @Autowired
    private DepositReadMapper depositReadMapper;

    @Autowired
    private OAuthAccessTokenWriteMapper oAuthAccessTokenWriteMapper;

    @Autowired
    private CustomerCardReadMapper customerCardReadMapper;

    @Override
    public void delete(String arg0) throws BusinessException {

    }

    @Override
    public Object get(Integer arg0) throws BusinessException {
        return null;
    }

    @Override
    public int insert(Object arg0) throws BusinessException {
        return 0;
    }

    @Override
    public List<?> query(QueryUtil arg0) {
        return null;
    }

    @Override
    public void update(Object arg0) throws BusinessException {

    }

    @Override
    public Boolean validate(Object arg0) throws BusinessException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Boolean validateForDelete(Object arg0) throws BusinessException {
        return null;
    }

    @Override
    public Boolean validateForInsert(Object arg0) throws BusinessException {
        return null;
    }

    @Override
    public Boolean validateForUpdate(Object  arg0) throws BusinessException {
        CustomerDTO dto = (CustomerDTO)arg0  ;
        if (dto.getUserId() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_USER_PARAMS_ISNULL);
        }
        if (StringUtils.isEmpty(dto.getPhone())) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_USER_PARAMS_ISNULL);
        }
        if (StringUtils.isEmpty(dto.getId())) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_USER_PARAMS_ISNULL);
        }
        return null;
    }

    @Override
    public List<Object> queryByPage(QueryUtil queryUtil) {
        queryUtil.getParams().put("userId", SecurityUtils.getCurrentLogin().getUserId());
        List<Object> customerList = customerReadMapper.getCustomerPage(queryUtil);
        StringBuffer errorMsg = new StringBuffer();

        HashMap<String, String> genderMap = new HashMap<String, String>();
/*        HashMap<String, String> hobbyMap = new HashMap<String, String>();
        HashMap<String, String> jobMap = new HashMap<String, String>();*/
        try {
            genderMap = getChineseNameByParentCode(SystemCodeEnum.GENDER.getCode());
      /*      jobMap = getChineseNameByParentCode(SystemCodeEnum.PROFESSION.getCode());
            hobbyMap = getChineseNameByParentCode(SystemCodeEnum.HOBBY.getCode());*/
        } catch (BusinessException e) {
            LOG.error("queryByPage error", e);
        }

        for (Object dto : customerList) {
            CustomerDTO customer = (CustomerDTO) dto;

          /*  List<String> hobbyCH = new ArrayList<String>();
            List<String> jobCH = new ArrayList<String>();
            if (customer.getJob() != null) {
                String[] job = customer.getJob().split(",");
                for (String child : job) {
                    jobCH.add(jobMap.get(child));
                }
            }
            if (customer.getHobby() != null) {
                String[] hobby = customer.getHobby().split(",");
                for (String child : hobby) {
                    hobbyCH.add(hobbyMap.get(child));
                }
            }*/
            String genderCH = genderMap.get(customer.getGender());
        /*    customer.setJobCH(jobCH);
            customer.setHobbyCH(hobbyCH);*/
            customer.setGenderCH(genderCH);
            dto = customer;
        }
        return customerList;
    }

    @Override
    public List<Object> queryVersionPage(QueryUtil queryUtil) {
        queryUtil.getParams().put("adminId", SecurityUtils.getCurrentLogin().getUserId());
        List<Object> customerList = customerVersionReadMapper.getCustomerPage(queryUtil);
        StringBuffer errorMsg = new StringBuffer();

        HashMap<String, String> genderMap = new HashMap<String, String>();
        HashMap<String, String> hobbyMap = new HashMap<String, String>();
        HashMap<String, String> jobMap = new HashMap<String, String>();
        HashMap<String, String> relationMap = new HashMap<String, String>();
        try {
            genderMap = getChineseNameByParentCode(SystemCodeEnum.GENDER.getCode());
            jobMap = getChineseNameByParentCode(SystemCodeEnum.PROFESSION.getCode());
            hobbyMap = getChineseNameByParentCode(SystemCodeEnum.HOBBY.getCode());
            relationMap = getChineseNameByParentCode(SystemCodeEnum.RELATION.getCode());
        } catch (BusinessException e) {
            LOG.error("queryByPage error", e);
        }

        for (Object dto : customerList) {
            CustomerDTO customer = (CustomerDTO) dto;

             List<String> hobbyCH = new ArrayList<String>();
            List<String> jobCH = new ArrayList<String>();
            if (customer.getJob() != null) {
                String[] job = customer.getJob().split(",");
                for (String child : job) {
                    jobCH.add(jobMap.get(child));
                }
            }
            if (customer.getHobby() != null) {
                String[] hobby = customer.getHobby().split(",");
                for (String child : hobby) {
                    hobbyCH.add(hobbyMap.get(child));
                }
            }

            if (customer.getEmergRelation() != null) {
                customer.setEmergRealtionCH(relationMap.get(customer.getEmergRelation()));
            }
            String genderCH = genderMap.get(customer.getGender());
            customer.setJobCH(jobCH);
            customer.setHobbyCH(hobbyCH);
            customer.setGenderCH(genderCH);
            dto = customer;
        }
        return customerList;
    }

    public HashMap<String, String> getChineseNameByParentCode(String codes) throws BusinessException {

        HashMap<String, String> map = new HashMap<String, String>();

        List<CodeDTO> codeDtoList = new ArrayList<CodeDTO>();
        List<Code> codeList = codeService.getCodeAndChildren(codes);
        if (codeList != null && codeList.size() > 0) {
            for (Code code : codeList) {
                CodeDTO codeDto = CodeConverter.fromCodeToCodeDTO(code);
                List<Code> childCodes = code.getChildCodes();
                if (childCodes != null && childCodes.size() > 0) {
                    codeDto.setHas_children(new Boolean(true).toString());
                    List<CodeDTO> childCodeDtos = CodeConverter.fromCodeListToDTOList(childCodes);
                    if (childCodeDtos != null) {
                        codeDto.setChildCodes(childCodeDtos);
                    }
                } else {
                    codeDto.setHas_children(new Boolean(false).toString());
                }
                codeDtoList.add(codeDto);
            }
        }
        map.put(codeDtoList.get(0).getCode(), codeDtoList.get(0).getCode_desc_zh());
        for (CodeDTO dto : codeDtoList.get(0).getChildCodes()) {
            map.put(dto.getCode(), dto.getCode_desc_zh());
        }

        return map;
    }

    @Override
    public synchronized Integer createCustomer(CustomerDTO customer) throws BusinessException {
        //检查用户名是否已经存在
        User pUser = new User();
        pUser.setLoginId(customer.getPhone());
        User existUser = itExistUser(pUser);
        if (existUser != null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_HASONE);
        }
        //检查idno是否存在
        if(!StringUtils.isEmpty(customer.getCertificatesNo())){
            HashMap queryMap = new HashMap();
            queryMap.put("idNo",customer.getCertificatesNo());
            List<Customer> cstIdNos = customerReadMapper.checkExistIDNo(queryMap);
            if(cstIdNos.size()>0){
                throw new LandseaBusinessException(LandseaErrorMessageEnum.USER_IDNO_ISEXIST);
            }
        }
        //插入用户
        UserDTO userDTO = new UserDTO();
        userDTO.setLoginId(customer.getPhone());
        userDTO.setPassword(SysUtil.MD5Digest(userDTO.getLoginId().substring(userDTO.getLoginId().length() - 6)));
        userDTO.setCustomerDTO(customer);
        clientUserServiceImpl.insert(userDTO);
        return 0;
    }

    public User itExistUser(User user) {
        return clientUserReadMapper.itExistUser(user);
    }

    public CustomerDTO customerToDTO(Customer customer) {
        CustomerDTO customerDTO = new CustomerDTO();
        if (customer.getBirthday() != null) {
            customerDTO.setBirthday(customer.getBirthday());
        }
        if (customer.getCertificatesAddress() != null) {
            customerDTO.setCertificatesAddress(customer.getCertificatesAddress());
        }
        if (customer.getCertificatesNo() != null) {
            customerDTO.setCertificatesNo(customer.getCertificatesNo());
        }
        if (customer.getCertificatesType() != null) {
            customerDTO.setCertificatesType(customer.getCertificatesType());
        }
        if (customer.getHobby() != null) {
            customerDTO.setHobby(customer.getHobby());
        }
        if (customer.getGender() != null) {
            customerDTO.setGender(customer.getGender());
        }
        if (customer.getImgUrl() != null) {
            customerDTO.setImgUrl(customer.getImgUrl());
        }
        if (customer.getJob() != null) {
            customerDTO.setJob(customer.getJob());
        }
        if (customer.getName() != null) {
            customerDTO.setName(customer.getName());
        }
        if (customer.getOpenId() != null) {
            customerDTO.setOpenId(customer.getOpenId());
        }
        if (customer.getPhone() != null) {
            customerDTO.setPhone(customer.getPhone());
        }
        if (customer.getUserId() != null) {
            customerDTO.setUserId(customer.getUserId());
        }
        if (customer.getNickName() != null) {
            customerDTO.setNickName(customer.getNickName());
        }
        if (customer.getUniId() != null) {
            customerDTO.setUniId(customer.getUniId());
        }
        return customerDTO;
    }

    @Override
    public Integer updateCustomer(CustomerDTO customer) throws Exception {
        validateForUpdate(customer);
        User existUser = itExistUser(new User(customer.getUserId(),customer.getPhone()));
        //如果证件号不为空，则需判断是否存在
        if(!StringUtils.isEmpty(customer.getCertificatesNo())){
            HashMap queryMap = new HashMap();
            queryMap.put("idNo",customer.getCertificatesNo());
            queryMap.put("id",customer.getId());
            List<Customer> cstIdNos = customerReadMapper.checkExistIDNo(queryMap);
            if(cstIdNos.size()>0){
                throw new LandseaBusinessException(LandseaErrorMessageEnum.USER_IDNO_ISEXIST);
            }
        }
        boolean uesdOpr = false;
        if (existUser != null){
           //  throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_HASONE);
            //判断是否有业务数据
            uesdOpr= checkUserExistContractDeposit(existUser.getId());
            //存在业务数据则抛出异常
            if(uesdOpr){
                throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_USER_LOGINID_ISACTIVE);
            }else{
                //不存在业务数据则清空该用户信息
                deleteExistCustomer(existUser);
            }
        }
        //check the phone and the account
        User user = clientUserReadMapper.selectByPrimaryKey(customer.getUserId());
        if (!user.getLoginId().equals(customer.getPhone())) {
            user.setLoginId(customer.getPhone());
            user.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            userWriteMapper.updateByPrimaryKeySelective(user);
        }
        //oldCustomerDTO = customerReadMapper.selectByPrimaryKey(customer.getId());
        //修改用户信息
        Customer customer1 = CustomerDTO.fromDTOtoCustomer(customer);
        customer1.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        customerWriteMapper.updateByPrimaryKeySelective(customer1);

        insertCustomerVersion(customer.getId(),null);
        return 0;
    }


    public Integer insertCustomerVersion(Integer customerId,Integer userId) throws Exception {
        Customer customerBak = null;
        if(customerId != null){
            customerBak = customerReadMapper.selectByPrimaryKey(customerId);
        }
        if(userId != null){
            customerBak = customerReadMapper.selectByUserId(userId);
        }
        if(customerBak == null){
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGIN_HASONE);
        }
        //插入历史记录表
        CustomerVersion customerVersion = new CustomerVersion();
        String[] excludsArray = {"id", "version", "lastModifiedDtm", "lastModifiedBy", "createdDtm", "createdBy", "deleted"};
        StringTools.copyPropertiesExclude(customerBak, customerVersion, excludsArray);
        customerVersion.setVersionNumber(VariableChar.DIR+ customerVersionReadMapper.getMaxVersionNumber(customerBak.getUserId()) );
        customerVersion.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        customerVersionWriteMapper.insertSelective(customerVersion);
        return customerVersion.getId();
    }


    @Override
    public CustomerVersion getNewVersion(Integer userId) {
        return customerVersionReadMapper.getNewVersion(userId);
    }



    /**
     * [描述]：事务已添加</br>
     *
     * @param ids
     * @return
     * @throws BusinessException
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {BusinessException.class})
    public Integer deleteCustomer(String ids) throws BusinessException {
        List<Integer> userIdsList = customerReadMapper.getCustomersById(ids);
        String userIds = userIdsList.toString();

        userService.delete(userIds.substring(1, userIds.length() - 1));
        customerWriteMapper.deleteCustomer(ids);

        return 0;
    }

    @Override
    public CustomerDTO getCustomerInfo(Integer id) {
        CustomerDTO customer = customerReadMapper.getCustomersByUserId(id);

        HashMap<String, String> genderMap = new HashMap<String, String>();
        HashMap<String, String> hobbyMap = new HashMap<String, String>();
        HashMap<String, String> jobMap = new HashMap<String, String>();
        try {
            genderMap = getChineseNameByParentCode(SystemCodeEnum.GENDER.getCode());
            jobMap = getChineseNameByParentCode(SystemCodeEnum.PROFESSION.getCode());
            hobbyMap = getChineseNameByParentCode(SystemCodeEnum.HOBBY.getCode());
        } catch (BusinessException e) {
            LOG.error("getCustomerInfo error", e);
        }
        List<String> hobbyCH = new ArrayList<String>();
        List<String> jobCH = new ArrayList<String>();
        if (customer.getJob() != null) {
            String[] job = customer.getJob().split(",");
            for (String child : job) {
                jobCH.add(jobMap.get(child));
            }
        }
        if (customer.getHobby() != null) {
            String[] hobby = customer.getHobby().split(",");
            for (String child : hobby) {
                hobbyCH.add(hobbyMap.get(child));
            }
        }
        String genderCH = genderMap.get(customer.getGender());
        customer.setJobCH(jobCH);
        customer.setHobbyCH(hobbyCH);
        customer.setGenderCH(genderCH);

        return customer;
    }

    @Override
    public CustomerDTO queryByLoginId(Customer customer) throws LandseaBusinessException {
        if (customer.getPhone() == null) {
            throw new LandseaBusinessException("账号必传");
        }
        CustomerDTO customerDTO = customerReadMapper.selectCustomerDTOByLoginId(customer.getPhone());
        if(customerDTO!=null){
            customerDTO.setCustomerCardDTO(customerCardReadMapper.queryCardInfoById(customerDTO.getUserId()));
        }
        return customerDTO;
    }

    @Override
    public List<ChapterUserDTO> selectChapterUserList(QueryUtil queryUtil) {
        return customerReadMapper.selectChapterUserList(queryUtil);
    }

    @Override
    public List<CustomerVersion> queryHistoryFiles(HashMap map) {
        return null;
    }

    @Override
    public Integer getChangeFlag(CustomerDTO customer)throws LandseaBusinessException{
        Integer resultFlag = 0;
        if (customer.getUserId() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.REGISTER_USER_LOGINID_ISNULL);
        }
        CustomerVersion customerVersion = customerVersionReadMapper.getNewVersion(customer.getUserId());
        StringBuffer newUser = new StringBuffer();
        newUser.append(customer.getName()).append(customer.getPhone()).append(customer.getCertificatesType()).append(customer.getCertificatesNo());
        StringBuffer latestUser = new StringBuffer();
        latestUser.append(customerVersion.getName()).append(customerVersion.getPhone()).append(customerVersion.getCertificatesType()).append(customerVersion.getCertificatesNo());
        LOG.info("update customer info is :" +newUser.toString() +"  | latest customer info is:"+ latestUser.toString());
        if(!newUser.toString().equals(latestUser.toString())){
            List<Contract> contractList = contractReadMapper.queryUsedContract(customer.getUserId());
            List<Deposit> depositList = depositReadMapper.queryUsedDeposit(customer.getUserId());
            if(contractList.size()>0 && depositList.size()>0){
                return LandeaConstants.HasType.ALL;
            }
            if(contractList.size()>0 && depositList.size()==0){
                return LandeaConstants.HasType.CONTRACT;
            }
            if(contractList.size()==0 && depositList.size()>0){
                return LandeaConstants.HasType.DEPOSIT;
            }
        }
        return resultFlag;
    }

    @Override
    public CustomerDTO queryByUserId(Customer customer) throws LandseaBusinessException {
        if (customer.getUserId() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.CONTRACT_USERID_ISNULL);
        }
        return customerReadMapper.selectCustomerDTOByUserId(customer.getUserId());
    }

    private boolean checkUserExistContractDeposit(Integer userId){
        Integer contracts = contractReadMapper.checkByUserId(userId);
        Integer deposits = depositReadMapper.checkUserDeposit(userId);
        if(contracts>0 || deposits>0){
            return true;
        }else{
            return false;
        }
    }

    private void deleteExistCustomer(User user){
        if(StringUtils.isEmpty(user.getLoginId())){
           return;
        }
        Integer systemId = SecurityUtils.getCurrentLogin().getUserId();
        String cellphone = user.getLoginId()+"_"+DateUtil.getInstence().convertYMDDate(new Date());
        //修改customer信息
        Customer customer = new Customer();
        customer.setUserId(user.getId());
        customer.setPhone(cellphone);
        customer.updateCommonInfo(systemId);
        customer.setDeleted(true);
       // customer.setCertificatesNo();
        customerWriteMapper.updateByUser(customer);
        //修改最新的版本变更信息
        customerVersionWriteMapper.deleteUserVersionByUserId(user.getId());
        //修改systemUser表信息
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setLoginId(cellphone);
        updateUser.updateCommonInfo(systemId);
        updateUser.setDeleted(true);
        userWriteMapper.updateByPrimaryKeySelective(updateUser);
        //-- 删除OAuthAccessToken --
        oAuthAccessTokenWriteMapper.deleteByLoginId(user.getLoginId());
        //删除 验证码发送记录
        verificationCodeWriteMapper.deleteByCellPhone(user.getLoginId());
    }
}
